package com.gopay.checkorder.service.task;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.dao.BankAuthOrderDAO;
import com.gopay.checkorder.service.AdPayAuthOrderService;
import com.gopay.checkorder.service.task.thread.AdpayAuthCheckOrderTaskThread;
import com.gopay.common.domain.bank.BankAuthOrder;

/**
 * 鉴权查询每小时对单任务
 * 
 * @AdPayCheckOrderPerHourTaskImpl.java
 * @author lilili
 * @2017-1-13 上午11:43:46 www.gopay.com.cn Inc.All rights reserved.
 */
public class AdPayCheckOrderPerHourTaskImpl implements Task {

	private final static Logger logger = LoggerFactory.getLogger("CHECK_ORDER");

	private final static int MAX_SIZE = 10000;

	@Resource(name = "bankAuthOrderDAO")
	private BankAuthOrderDAO bankAuthOrderDAO;

	@Resource(name = "adPayAuthOrderService")
	private AdPayAuthOrderService adPayAuthOrderService;

	private String bank;

	private final static int THREAD_SIZE = 10;
	private ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_SIZE);

	private void printLog(StopWatch sw, String bank, String prefix) {
		sw.split();
		logger.error(prefix + "------,bank=" + bank + ",耗时=" + sw.getSplitTime());
	}

	/**
	 * 任务执行
	 */
	public void doTask() {
		try {
			StopWatch sw = new StopWatch();
			sw.start();
			printLog(sw, bank, "AdPayCheckOrderPerHourTaskImpl------start");

			int pageSize = 100;
			int pageIndex = 1;
			int count = 0;

			Date date = new Date();
			int resCount = getCheckOrderCount(date);
			printLog(sw, bank, " ------对单总数量=" + resCount);

			List<BankAuthOrder> list = null;
			while (count < resCount) {
				list = getCheckOrder(date, pageIndex, pageSize);
				if (list == null || list.size() == 0) {
					printLog(sw, bank, "AdPayCheckOrderPerHourTaskImpl------分页为空，跳出while循环");
					break;
				}
				printLog(sw, bank, "AdPayCheckOrderPerHourTaskImpl------list.size()=" + list.size() + ",pageIndex=" + pageIndex);

				// 订单队列
				ConcurrentLinkedQueue<BankAuthOrder> queue = new ConcurrentLinkedQueue<BankAuthOrder>();
				queue.addAll(list);

				// 同步锁存器
				CountDownLatch latch = new CountDownLatch(queue.size());

				// 线程池中线程全部参与
				for (int i = 0; i < THREAD_SIZE; i++) {
					AdpayAuthCheckOrderTaskThread thread = new AdpayAuthCheckOrderTaskThread(adPayAuthOrderService, queue, latch);
					threadPool.execute(thread);

				}

				// 同步锁存器等待所有线程执行完成
				if (!latch.await(118, TimeUnit.SECONDS)) {
					logger.error("同步锁存器等待超时了 latch.count=" + latch.getCount());
					threadPool.awaitTermination(1, TimeUnit.SECONDS);
				}

				count += pageSize;
				pageIndex++;

			}

			printLog(sw, bank, "AdPayCheckOrderPerHourTaskImpl------结束while循环,resCount=" + resCount);

			printLog(sw, bank, "AdPayCheckOrderPerHourTaskImpl------end");
			sw.stop();

		} catch (Throwable t) {
			logger.error("执行对单Task时出现异常", t);
		}
	}

	/**
	 * 待对账订单笔数
	 * 
	 * @param orderStatus
	 * @param totalCheckTimes
	 * @return
	 */
	protected int getCheckOrderCount(Date date) {
		int resCount = bankAuthOrderDAO.getCheckOrderCount(date);

		if (resCount > MAX_SIZE) {
			resCount = MAX_SIZE;
		}
		return resCount;
	}

	/**
	 * 分页查询对账记录
	 * 
	 * @param orderStatus
	 * @param totalCheckTimes
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 */
	protected List<BankAuthOrder> getCheckOrder(Date date, int pageIndex, int pageSize) {

		return bankAuthOrderDAO.getCheckOrder(date, pageIndex, pageSize);
	}

	public void setBank(String bank) {
		this.bank = bank;
	}

}
